from typing import Dict, Any, Optional, List
from datetime import datetime, timedelta
from decimal import Decimal
from enum import Enum
import json

class QuotaType(str, Enum):
    """配额类型"""
    DAILY_REQUESTS = "daily_requests"      # 每日请求次数
    DAILY_COST = "daily_cost"             # 每日成本限额
    MONTHLY_REQUESTS = "monthly_requests"  # 每月请求次数
    MONTHLY_COST = "monthly_cost"         # 每月成本限额
    CONCURRENT_TASKS = "concurrent_tasks"  # 并发任务数
    VIDEO_DURATION = "video_duration"     # 视频时长限制
    FILE_SIZE = "file_size"               # 文件大小限制

class QuotaStatus(str, Enum):
    """配额状态"""
    AVAILABLE = "available"    # 可用
    WARNING = "warning"        # 警告（接近限额）
    EXCEEDED = "exceeded"      # 已超限
    SUSPENDED = "suspended"    # 暂停

class UserQuotaManager:
    """用户配额管理器"""
    
    def __init__(self):
        # 默认配额设置
        self.default_quotas = {
            QuotaType.DAILY_REQUESTS: 100,      # 每日100次请求
            QuotaType.DAILY_COST: Decimal("10.00"),   # 每日$10成本
            QuotaType.MONTHLY_REQUESTS: 3000,   # 每月3000次请求
            QuotaType.MONTHLY_COST: Decimal("300.00"), # 每月$300成本
            QuotaType.CONCURRENT_TASKS: 3,      # 最多3个并发任务
            QuotaType.VIDEO_DURATION: 300,     # 最长5分钟视频
            QuotaType.FILE_SIZE: 100 * 1024 * 1024  # 100MB文件限制
        }
        
        # VIP用户配额
        self.vip_quotas = {
            QuotaType.DAILY_REQUESTS: 1000,
            QuotaType.DAILY_COST: Decimal("100.00"),
            QuotaType.MONTHLY_REQUESTS: 30000,
            QuotaType.MONTHLY_COST: Decimal("3000.00"),
            QuotaType.CONCURRENT_TASKS: 10,
            QuotaType.VIDEO_DURATION: 600,     # 10分钟
            QuotaType.FILE_SIZE: 500 * 1024 * 1024  # 500MB
        }
        
        # 警告阈值（使用量达到限额的百分比时警告）
        self.warning_thresholds = {
            QuotaType.DAILY_REQUESTS: 0.8,
            QuotaType.DAILY_COST: 0.8,
            QuotaType.MONTHLY_REQUESTS: 0.8,
            QuotaType.MONTHLY_COST: 0.8,
            QuotaType.CONCURRENT_TASKS: 0.9,
        }
    
    def get_user_quotas(self, user_id: int, is_vip: bool = False) -> Dict[QuotaType, Any]:
        """获取用户配额设置"""
        if is_vip:
            return self.vip_quotas.copy()
        return self.default_quotas.copy()
    
    def get_current_usage(self, user_id: int, quota_type: QuotaType, period: str = "daily") -> Dict[str, Any]:
        """获取用户当前使用量"""
        # 这里需要从数据库或Redis获取实际使用量
        # 目前返回模拟数据
        
        now = datetime.now()
        if period == "daily":
            start_time = now.replace(hour=0, minute=0, second=0, microsecond=0)
        elif period == "monthly":
            start_time = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
        else:
            start_time = now - timedelta(hours=24)
        
        # 模拟使用量数据
        usage_data = {
            "user_id": user_id,
            "quota_type": quota_type.value,
            "period": period,
            "start_time": start_time.isoformat(),
            "end_time": now.isoformat(),
            "current_usage": self._get_mock_usage(user_id, quota_type),
            "last_updated": now.isoformat()
        }
        
        return usage_data
    
    def check_quota(self, user_id: int, quota_type: QuotaType, requested_amount: float, is_vip: bool = False) -> Dict[str, Any]:
        """检查用户配额是否足够"""
        
        # 获取用户配额限制
        quotas = self.get_user_quotas(user_id, is_vip)
        limit = quotas.get(quota_type, 0)
        limit_float = float(limit) if isinstance(limit, Decimal) else limit
        
        # 获取当前使用量
        if quota_type in [QuotaType.DAILY_REQUESTS, QuotaType.DAILY_COST]:
            usage_data = self.get_current_usage(user_id, quota_type, "daily")
        elif quota_type in [QuotaType.MONTHLY_REQUESTS, QuotaType.MONTHLY_COST]:
            usage_data = self.get_current_usage(user_id, quota_type, "monthly")
        else:
            usage_data = self.get_current_usage(user_id, quota_type, "current")
        
        current_usage = usage_data["current_usage"]
        
        # 计算是否超限
        after_usage = current_usage + requested_amount
        is_exceeded = after_usage > limit_float
        
        # 计算状态
        usage_percentage = after_usage / limit_float if limit_float > 0 else 1.0
        warning_threshold = self.warning_thresholds.get(quota_type, 0.8)
        
        if is_exceeded:
            status = QuotaStatus.EXCEEDED
        elif usage_percentage >= warning_threshold:
            status = QuotaStatus.WARNING
        else:
            status = QuotaStatus.AVAILABLE
        
        return {
            "quota_type": quota_type.value,
            "limit": limit_float,
            "current_usage": current_usage,
            "requested_amount": requested_amount,
            "after_usage": after_usage,
            "remaining": max(0, limit_float - after_usage),
            "usage_percentage": usage_percentage,
            "status": status.value,
            "is_exceeded": is_exceeded,
            "can_proceed": not is_exceeded,
            "warning_threshold": warning_threshold
        }
    
    def check_multiple_quotas(self, user_id: int, checks: List[Dict[str, Any]], is_vip: bool = False) -> Dict[str, Any]:
        """批量检查多个配额"""
        
        results = []
        can_proceed = True
        
        for check in checks:
            quota_type = QuotaType(check["quota_type"])
            requested_amount = check["requested_amount"]
            
            result = self.check_quota(user_id, quota_type, requested_amount, is_vip)
            results.append(result)
            
            if result["is_exceeded"]:
                can_proceed = False
        
        return {
            "user_id": user_id,
            "can_proceed": can_proceed,
            "checks": results,
            "timestamp": datetime.now().isoformat()
        }
    
    def estimate_task_quotas(self, user_id: int, task_params: Dict[str, Any]) -> List[Dict[str, Any]]:
        """估算任务需要的配额"""
        
        checks = []
        
        # 请求次数配额
        checks.append({
            "quota_type": QuotaType.DAILY_REQUESTS.value,
            "requested_amount": 1
        })
        
        # 成本配额
        estimated_cost = self._estimate_task_cost(task_params)
        checks.append({
            "quota_type": QuotaType.DAILY_COST.value,
            "requested_amount": float(estimated_cost)
        })
        
        # 并发任务配额
        checks.append({
            "quota_type": QuotaType.CONCURRENT_TASKS.value,
            "requested_amount": 1
        })
        
        # 视频时长配额
        if task_params.get("service_type") == "video_generation":
            duration = task_params.get("duration", 10)
            checks.append({
                "quota_type": QuotaType.VIDEO_DURATION.value,
                "requested_amount": duration
            })
        
        return checks
    
    def update_usage(self, user_id: int, quota_type: QuotaType, amount: float) -> bool:
        """更新用户使用量"""
        # 这里应该更新数据库或Redis中的使用量数据
        # 目前返回模拟结果
        return True
    
    def get_quota_summary(self, user_id: int, is_vip: bool = False) -> Dict[str, Any]:
        """获取用户配额总览"""
        
        quotas = self.get_user_quotas(user_id, is_vip)
        summary = {
            "user_id": user_id,
            "is_vip": is_vip,
            "quotas": {},
            "overall_status": "healthy",
            "warnings": [],
            "timestamp": datetime.now().isoformat()
        }
        
        warning_count = 0
        exceeded_count = 0
        
        for quota_type, limit in quotas.items():
            usage_data = self.get_current_usage(user_id, quota_type)
            current_usage = usage_data["current_usage"]
            
            # 转换为一致的数值类型进行计算
            limit_float = float(limit) if isinstance(limit, Decimal) else limit
            usage_percentage = current_usage / limit_float if limit_float > 0 else 0
            warning_threshold = self.warning_thresholds.get(quota_type, 0.8)
            
            if current_usage >= limit_float:
                status = QuotaStatus.EXCEEDED.value
                exceeded_count += 1
            elif usage_percentage >= warning_threshold:
                status = QuotaStatus.WARNING.value
                warning_count += 1
                summary["warnings"].append(f"{quota_type.value} 使用量已达到 {usage_percentage:.1%}")
            else:
                status = QuotaStatus.AVAILABLE.value
            
            summary["quotas"][quota_type.value] = {
                "limit": limit_float,
                "current_usage": current_usage,
                "remaining": max(0, limit_float - current_usage),
                "usage_percentage": usage_percentage,
                "status": status
            }
        
        # 设置总体状态
        if exceeded_count > 0:
            summary["overall_status"] = "exceeded"
        elif warning_count > 0:
            summary["overall_status"] = "warning"
        else:
            summary["overall_status"] = "healthy"
        
        return summary
    
    def _get_mock_usage(self, user_id: int, quota_type: QuotaType) -> float:
        """获取模拟使用量数据"""
        # 基于用户ID和配额类型生成一致的模拟数据
        import hashlib
        seed = int(hashlib.md5(f"{user_id}_{quota_type.value}".encode()).hexdigest()[:8], 16)
        
        quotas = self.get_user_quotas(user_id)
        limit = quotas.get(quota_type, 100)
        
        # 对于演示用户，使用较低的使用量
        if user_id >= 12345:  # 演示用户
            usage_rate = 0.1 + (seed % 20) / 100.0  # 0.1-0.3之间的使用率
        else:
            usage_rate = 0.1 + (seed % 60) / 100.0  # 原来的0.1-0.7之间的使用率
        
        # 确保返回一致的float类型
        limit_float = float(limit) if isinstance(limit, Decimal) else limit
        return limit_float * usage_rate
    
    def _estimate_task_cost(self, task_params: Dict[str, Any]) -> Decimal:
        """估算任务成本"""
        base_cost = Decimal("0.10")  # 降低基础成本用于演示
        
        # 根据任务类型调整
        service_type = task_params.get("service_type", "image_generation")
        if service_type == "video_generation":
            base_cost = Decimal("0.20")  # 视频生成基础成本
        elif service_type == "image_editing":
            base_cost = Decimal("0.15")
        
        # 根据参数调整
        duration = task_params.get("duration", 10)
        resolution = task_params.get("resolution", "1280x720")
        
        # 分辨率倍数
        resolution_multiplier = {
            "640x480": Decimal("1.0"),
            "1280x720": Decimal("1.2"),
            "1920x1080": Decimal("1.5"),
            "3840x2160": Decimal("2.5")
        }.get(resolution, Decimal("1.2"))
        
        return base_cost * Decimal(str(duration)) * resolution_multiplier

# 全局配额管理器实例
quota_manager = UserQuotaManager()